#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Dec 26 01:39:39 2019

@author: bing
"""
import random

from flask import Flask, render_template,redirect, request, jsonify
from werkzeug.utils import secure_filename
import os
import cv2
import time
from myUtil import parse_result, isFakePlate
from datetime import timedelta
import pandas as pd
import numpy as np
from paddle_online_0911 import recognize_plate_online
# import darknet as dn
# from hyperlpr import HyperLPR_PlateRecogntion as plateRecog  # 车牌识别库
# from hyperlpr import HyperLPR_plate_recogntion as plateRecog
from keras.preprocessing.image import img_to_array
from keras.models import load_model


#设置允许的文件格式
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])

#vehicle_info_database = pd.read_csv('vehicle-database.csv')
cwd_path = os.getcwd()
cfg_path = cwd_path + "/cfg/yolov3-voc.cfg"
weights_path = cwd_path + "/cfg/yolov3-voc_final.weights"
data_path = cwd_path + "/cfg/voc.data"

VEHICLE_WIDTH = 28
VEHICLE_HEIGHT = 28
v_color_model_path = cwd_path + "/cfg/vehicle_color.hdf5" #
v_type_model_path = cwd_path + "/cfg/vehicle_type.hdf5"

global vehicle_info_database,net,meta

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

 
def prepare_service():
    global vehicle_info_database
    # 
    vehicle_info_database = pd.read_csv('vehicle-database.csv')
   
    return vehicle_info_database

 # 生成随机文件名
# def generate_random_filename(filename):
#     random_number = random.randint(1, 10000)
#     timestamp = int(time.time())
#     extension = os.path.splitext(filename)[1]
#     return f"{secure_filename(filename)}_{random_number}_{timestamp}{extension}"

# 生成只包含时间戳和后缀名的文件名
def generate_random_filename(filename):
    timestamp = int(time.time())  # 生成当前时间戳
    extension = os.path.splitext(filename)[1]  # 获取文件的后缀名（包括点，如 ".jpg"）
    return f"{timestamp}{extension}"
    
# 预测模块，输入图片，分析车牌信息和子品牌，跟车辆信息库对比查询，判定是否为嫌疑车辆
def predict(imgPath, vehicle_info_database):
    predictResult = "未识别"
    plateNo = "未识别"
    carBrandZh = "未识别"
    original_image = cv2.imread(imgPath)
 #加载配置文件和权重
    # net = dn.load_net(cfg_path.encode('utf-8'), weights_path.encode('utf-8'), 0)
    # meta = dn.load_meta(data_path.encode('utf-8'))

    # if net is None or meta is None:
    #     raise ValueError("模型加载失败，请检查配置文件和权重文件。")
    
    v_color_model = load_model(v_color_model_path)
    v_type_model = load_model(v_type_model_path)

    # predict_result_dict = dn.detect(net, meta, imgPath.encode('utf-8'))

    # import requests

    # url = "http://127.0.0.1/:5000/detect"
    # files = {'file': open('test.jpg', 'rb')}
    # predict_result_dict = requests.post(url, files=files)

    # import requests

    # url = "http://localhost:8090/detect"
    # # files = {'file': open('path/to/your/image.jpg', 'rb')}
    # # 读取图片内容
    # with open(imgPath, 'rb') as img_file:
    #     img_data = img_file.read()
    #
    # # files = {'file': open(imgPath, 'rb')}
    #
    # # 发送图片内容，而不是文件路径
    # files = {'file': ('image.jpg', img_data, 'image/jpeg')}
    # print(f"request files: {files}")
    # response = requests.post(url, files=files)
    #
    # print(f"response: {response}")

    # import requests
    # import json
    #
    # url = "http://localhost:8090/detect"
    # imgPath = "/Users/jackiezheng/liushi/FindFakePlateVehicle-web/test.jpg"
    #
    # with open(imgPath, 'rb') as img_file:
    #     files = {'file': ('test.jpg', img_file, 'image/jpeg')}
    #
    #     try:
    #         response = requests.post(url, files=files)
    #         response.raise_for_status()  # 如果状态码不是 200，将引发异常
    #
    #         print(f"Status Code: {response.status_code}")
    #         print(f"Response Content: {response.text}")
    #
    #         # 尝试解析 JSON 响应
    #         try:
    #             json_response = response.json()
    #             print(f"Parsed JSON Response: {json.dumps(json_response, ensure_ascii=False, indent=2)}")
    #         except json.JSONDecodeError:
    #             print("Response is not valid JSON")
    #
    #     except requests.exceptions.RequestException as e:
    #         print(f"An error occurred: {e}")
    #         if hasattr(e, 'response'):
    #             print(f"Response status code: {e.response.status_code}")
    #             print(f"Response content: {e.response.text}")
    #
    #
    # if response.status_code == 200:
    #     detections = response.json()
    #     # 将 JSON 格式转换回类似 dn.detect 的格式
    #     # original_format = [
    #     predict_result_dict = [
    #         (
    #             d['label'],
    #             d['confidence'],
    #             (d['bbox']['x'], d['bbox']['y'], d['bbox']['width'], d['bbox']['height'])
    #         )
    #         for d in detections
    #     ]
    #
    #     # print(original_format)
    #     print(predict_result_dict)
    # else:
    #     print("Error:", response.status_code, response.text)

    import subprocess
    import json

    # curl 命令
    curl_command = [
        'curl',
        '-X', 'POST',
        'http://localhost:8090/detect',
        '-F', 'file=@/Users/jackiezheng/liushi/FindFakePlateVehicle-web/static/images/test.jpg'
    ]

    try:
        # 运行 curl 命令
        result = subprocess.run(curl_command, capture_output=True, text=True, check=True)

        # 打印状态码（curl 成功时总是返回 0）
        print(f"Command executed with return code: {result.returncode}")

        # 打印输出
        print("Response:")
        print(result.stdout)

        # 尝试解析 JSON 响应
        try:
            json_response = json.loads(result.stdout)
            print("Parsed JSON response:")
            print(json.dumps(json_response, ensure_ascii=False, indent=2))
        except json.JSONDecodeError:
            print("Response is not valid JSON")

    except subprocess.CalledProcessError as e:
        print(f"Command failed with return code {e.returncode}")
        print("Error output:")
        print(e.stderr)

    except Exception as e:
        print(f"An error occurred: {e}")

    # print(f"predict_result_dict before: {predict_result_dict}")

    # predict_result_dict = {"bbox": {"height": 499.37078857421875, "width": 547.970703125, "x": 677.2782592773438, "y": 427.50067138671875},
    #   "confidence": 0.9998480677604675, "label": "\u96ea\u4f5b\u5170"}

    predict_result_dict = [{
        "bbox": {"height": 499.37078857421875, "width": 547.970703125, "x": 677.2782592773438, "y": 427.50067138671875},
        "confidence": 0.9998480677604675, "label": "\u96ea\u4f5b\u5170"}]

    print(f"predict_result_dict: {predict_result_dict}")

    result_dict = parse_result(predict_result_dict) # 结果进行后处理
    
    for i in range(result_dict["b_box_num"]):
        
        x1_min = result_dict["detection_boxes"][i][0]
        y1_min = result_dict["detection_boxes"][i][1]
        
        x1_max = result_dict["detection_boxes"][i][2]
        y1_max = result_dict["detection_boxes"][i][3]
        carBrandZh = result_dict["detection_classes"][i] # 在线模型输出直接是中文字符串，而之前的离线模型是ascii编码的字符串

        print(f"carBranZh {carBrandZh}")
       # 截取汽车检测框的下面1/3部分，作为车牌检测的子区域。调用车牌识别，准确率和计算速度有保证
        left = x1_min
        top = int(y1_min + (y1_max - y1_min)*0.67)
        right = x1_max
        bottom = y1_max
        crop_image = original_image[top:bottom, left:right]

        # 使用随机文件名保存图片
        crop_image_filename = generate_random_filename('crop_image.jpg')
        gray_image_filename = generate_random_filename('gray_image.jpg')
        roi_image_filename = generate_random_filename('roi_image.jpg')

        # 保存 crop_image
        # cv2.imwrite('crop_image.jpg', crop_image)
        cv2.imwrite(crop_image_filename, crop_image)
        grayImg = cv2.cvtColor(crop_image, cv2.COLOR_BGR2GRAY)
        # 保存 grayImg
        # cv2.imwrite('gray_image.jpg', grayImg)
        cv2.imwrite(gray_image_filename, grayImg)
        roi_img = cv2.resize(grayImg, (VEHICLE_WIDTH, VEHICLE_HEIGHT))
        roi_img = roi_img.astype("float")/255.0
        roi_img = img_to_array(roi_img)
        roi_img = np.expand_dims(roi_img, axis=0)

        # 保存 roi_img（转换为 8 位图像以便保存）
        # cv2.imwrite('roi_image.jpg', (roi_img[0] * 255).astype(np.uint8))
        cv2.imwrite(roi_image_filename, (roi_img[0] * 255).astype(np.uint8))

        (bus,car,minibus,truck) = v_type_model.predict(roi_img)[0]
        # cv2.imwrite('roi_img.jpg', roi_img)
        print(f"bus,car,minibus,truck{bus,car,minibus,truck}")
        v_type_result = {"bus":bus,"car":car,"minibus":minibus,"truck":truck}
        v_type_label = max(v_type_result,key=v_type_result.get)
        
        (black,blue,brown,green,red,silver,white,yellow ) = v_color_model.predict(roi_img)[0]
        v_color_result = {"black":black,"blue": blue, "brown":brown, "green":green, "red": red, "silver":silver,"white":white,"yellow":yellow}
        v_color_label = max(v_color_result, key=v_color_result.get)

        # 识别车牌号码信息
        # plateInfo = plateRecog(crop_image)
        plateNo = recognize_plate_online(imgPath)
        # if plateInfo:
        if plateNo:
            # 读取识别结果中的车牌号码
            # plateNo = plateInfo[0][0]
            inputCarInfo = [plateNo, carBrandZh]
            # print(inputCarInfo)
            isFake, true_car_brand = isFakePlate(inputCarInfo, vehicle_info_database)
            if isFake:
               predictResult = "这是一辆套牌车" 
            else:
               predictResult = "这是一辆正常车"    
        else:
            plateNo = "未识别"
            #carBrandZh = "未识别"
            predictResult = "车牌未识别，无法判定" 
            
    return plateNo, v_type_label, v_color_label, carBrandZh, predictResult
# ------------------------------------------------------------------------------------------------------------------------
app = Flask(__name__)
# 设置静态文件缓存过期时间
app.send_file_max_age_default = timedelta(seconds=1)
vehicle_info_database = prepare_service()


@app.route('/prepare')
def warm_up():
    vehicle_info_database = prepare_service()
    return redirect('/')


@app.route('/', methods=['POST', 'GET'])  #` 添加路由
def analyze():
    print("testing")
    if request.method == 'POST':
        f = request.files['file']
 
        if not (f and allowed_file(f.filename)):
            return jsonify({"error": 1001, "msg": "请检查上传的图片类型，仅限于png、PNG、jpg、JPG、bmp"})

        basepath = os.path.dirname(__file__)  # 当前文件所在路径

        # upload_path = os.path.join(basepath, 'static/images', secure_filename(f.filename))  # 注意：没有的文件夹一定要先创建，不然会提示没有该路径
        # upload_path = os.path.join(basepath, 'static/images', generate_random_filename(f.filename))
        relative_path = os.path.join('static/images', generate_random_filename(f.filename))  # 使用相对路径
        upload_path = os.path.join(basepath, relative_path)  # 拼接成绝对路径

        # randomNumber = random.randint(1, 10000)
        # upload_path_ramdom = os.path.join(basepath, 'static/images', secure_filename(f.filename) + str(randomNumber))
        f.save(upload_path)
        # f.save(upload_path_ramdom)
          
        # 使用Opencv转换一下图片格式和名称
        # read_path = os.path.join('./static/images', secure_filename(f.filename))
        # img = cv2.imread(upload_path)
        read_path = os.path.join('./', relative_path)
        print(f"read path: {read_path}")
        img = cv2.imread(read_path)
        # img = cv2.imread(relative_path)
        # img = cv2.imread(read_path)
        img_path = os.path.join(basepath, 'static/images', 'test.jpg')
        cv2.imwrite(img_path, img)
        # cv2.imwrite(os.path.join(basepath, 'static/images', 'test.jpg'), img)
        # img_path = 'static/images/test.jpg'
        read_path2 = "./static/images/test.jpg"
        # plate_no,v_type,v_color,car_brand, predict_result = predict(img_path, vehicle_info_database)
        plate_no, v_type, v_color, car_brand, predict_result = predict(read_path2, vehicle_info_database)
        context = ["车牌号："+plate_no,"车型："+ v_type,"车辆颜色："+v_color, "车辆品牌："+car_brand, "结论："+predict_result]
        
        return render_template('index.html', context = context, val1=time.time())
 
    return render_template('index.html')
 
 
if __name__ == '__main__':
    # app.debug = True
    app.run(host="0.0.0.0", port=5000, debug=True)
